/*
 * @Author: jingyitao
 * @Date: 2023-08-26 13:51:41
 * @Last Modified by: jingyitao
 * @Last Modified time: 2023-12-29 15:50:02
 * 在新版本的 axios 中使用 AxiosRequestConfig 类型约束报错时 可以使用 InternalAxiosRequestConfig 做类型约束
 */

import LocalCache from '../storage/index'
import { ElMessage } from 'element-plus'
import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig, AxiosResponse } from 'axios'

type Result<T> = {
  code: number
  succeeded: boolean
  data: T
  message: string
}

// 基础配置
export const baseConfig: AxiosRequestConfig = {
  baseURL: 'http://10.11.20.26:3000/api',
  timeout: 60000,
  withCredentials: true,
}

// 导出 Request 类,可以自定义参数实例化
export class Request {
  // axios 实例
  instance: AxiosInstance
  // 基础配置
  baseConfig: AxiosRequestConfig = baseConfig
  constructor(config: AxiosRequestConfig) {
    // 创建实例
    this.instance = axios.create({ ...this.baseConfig, ...config })

    // 请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 可以在这里做请求头的配置 如 AppKey、token 等 视项目情况而定
        // const token = LocalCache.getCache('token')
        // config.headers['token'] = token
        return config
      },
      // 请求出错 全局提示
      (error) => {
        // return Promise.reject(error)
        return ElMessage(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        // 可以直接返回 服务器返回的 response 也可以做自定义处理
        return response
      },
      (error) => {
        // 处理常见的 http 错误请求
        let message = 'server error'
        switch (error.response.status) {
          case 400:
            message = '请求错误(400)'
            break
          case 401:
            message = '未授权，请重新登录(401)'
            // 这里可以做清空storage并跳转到登录页的操作
            break
          case 403:
            message = '拒绝访问(403)'
            break
          case 404:
            message = '请求出错(404)'
            break
          case 408:
            message = '请求超时(408)'
            break
          case 500:
            message = '服务器错误(500)'
            break
          case 501:
            message = '服务未实现(501)'
            break
          case 502:
            message = '网络错误(502)'
            break
          case 503:
            message = '服务不可用(503)'
            break
          case 504:
            message = '网络超时(504)'
            break
          case 505:
            message = 'HTTP版本不受支持(505)'
            break
          default:
            message = `连接出错(${error.response.status})!`
        }
        ElMessage(message)
        return Promise.reject(error)
      }
    )
  }

  // 定义请求方法
  public request(config: AxiosRequestConfig): Promise<AxiosResponse> {
    return this.instance.request(config)
  }

  // get 请求 Result<T>
  public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.get(`${url}&t=${new Date().getTime()}`, config)
  }

  // post 请求 Result<T>
  public post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.post(url, data, config)
  }

  // put 请求 Result<T>
  public put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.put(url, data, config)
  }

  // delete 请求 Result<T>
  public delete<T = any>(url: string, config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.delete(url, config)
  }
}

// 导出一个实例对象
export default new Request({})
